离线地图显示 (离线矢量地图)Sample详情 (离线瓦片地图)Sample详情

最后更新时间:2020年12月4日

离线地图显示方法

离线地图数据类型包括离线矢量地图和离线瓦片地图,两种地图加载显示的方式也略有不同:

加载地图有多种方法,不同的方法适用于不同的数据类型,具有不同的应用场景。离线矢量地图、离线瓦片地图显示的核心方法如下表所示,从表中可以观察到,它们具有三种相同的方法,另外各自具有一种独有的方法,开发者可根据数据类型、实际需求来确定采用哪种方法。

方法 接口 地图类型 使用场景
加载地图文档 loadFromFile / loadFromFileAsync 矢量 / 瓦片 最常用,适于地图文档中只有一个地图的情况,若有多个地图则默认加载第一个。
加载地图文档对应索引的地图 loadFromDocument / loadFromDocumentAsync 矢量 / 瓦片 适于加载有多个地图的地图文档,可控制加载某个地图。
通过地图文档获取Map setMap / setMapAsync 矢量 / 瓦片 适于加载地图之前需处理的情况,如删除部分图层、获取信息等。
通过数据库创建图层,从而构建Map setMap / setMapAsync 矢量 源数据为离线矢量数据(.hdb数据库,兼容.mgdb数据库),没有组织地图文档“.mapx”时,只能采用此方法。
基于ServerLayer实例化Map setMap / setMapAsync 瓦片 直接使用代码加载瓦片地图(.mut瓦片),不用在桌面工具中配置地图文档。

加载离线矢量地图

一般有如下四种方式:

一、加载离线矢量地图文档: loadFromDocument / loadFromDocumentAsync

调用loadFromDocument / loadFromDocumentAsync方法加载地图文档,此方法是加载离线地图最常用、最简单的一种。前提是必须事先组织配置好mapx地图文档文件。

0203MapView加载地图接口1.png

//引用类库(无需开发人员手动编写)
//import com.zondy.mapgis.android.mapview.MapView;  10.3版本
import com.zondy.mapgis.map.view.mapview.MapView;
//import com.zondy.mapgis.android.environment.Environment.AuthorizeCallback;  10.3版本
import com.zondy.mapgis.environment.Environment.AuthorizeCallback;


//定义MapView对象
private MapView mMapView;
//获取移动端设备sd卡的根目录
public final static String rootPath = Environment.getExternalStorageDirectory().getPath();
public final static String systemPath = Environment.getExternalStorageDirectory().getPath() + "/MapGISSample/";

//环境初始化,必须在使用SDK各组件之前调用,会自动建立根目录结构
com.zondy.mapgis.environment.Environment.initialize(systemPath, this);
//授权请求
com.zondy.mapgis.environment.Environment.requestAuthorization(this, new AuthorizeCallback() {
    @Override
    //授权完成后回调
    public void onComplete() {
        //获取MapView对象
        mMapView = (MapView) findViewById(R.id.mapView);
        //同步方法
        mMapView.loadFromFile(MainActivity.rootPath + "/MapGISSample/Map/MapShow/WuHan/WuHan.mapx");

        //异步方法
        mMapView.loadFromFileAsync(MainActivity.rootPath + "/MapGISSample/Map/MapShow/WuHan/WuHan.mapx");  
        //异步加载地图回调监听
        mMapView.setMapLoadListener(new MapView.MapViewMapLoadListener() {
            @Override
            public void mapViewWillStartLoadingMap(MapView arg0, String arg1) {
                //开始加载地图
            }
        
            @Override
            public void mapViewDidFinishLoadingMap(MapView arg0, String arg1) {
                //地图加载完成
            }
        
            @Override
            public void mapViewDidFailLoadingMap(MapView arg0, String arg1) {
                //地图加载失败
            }
        });
    }

});

代码说明:如果采用异步方法加载地图,可以为地图视图设置地图加载回调监听器,监听地图的加载情况。

二、加载离线矢量地图文档对应索引的地图:loadFromDocument / loadFromDocumentAsync

通过loadFromDocument / loadFromDocumentAsync来加载地图文档对应索引的地图,可以加载mapx地图文档中的指定地图,同样适用于离线矢量地图、离线瓦片地图。

0203MapView加载地图接口1.png 0204Document打开地图文档接口.png


//创建文档对象
Document mapDoc = new Document();
//打开地图文档
mapDoc.open(MainActivity.rootPath+"/MapGISSample/Map/MapShow/WuHan/WuHan.mapx");
//同步方法:在地图视图中加载第1个地图
mMapView.loadFromDocument(mapDoc, 0);
//异步方法:利用地图加载完成的回调方法判断地图加载是否成功
mMapView.loadFromDocumentAsync(mapDoc, 0, new MapViewFinishCallback() {
    @Override
    public void onDidFinish(boolean arg0) {
        if (arg0) {
            //地图加载完成
        } else {
            //地图加载失败
        }
    }
});

三、通过地图文档获取Map:setMap / setMapAsync

通过地图文档Document获取Map,调用setMap / setMapAsync方法加载地图。同样可以加载地图文档中指定的地图。

0203MapView加载地图接口2.png 0205Document获取地图列表.png 0206Maps获取地图接口.png

//创建文档对象
Document mapDoc = new Document();
//打开地图文档
mapDoc.open(MainActivity.rootPath+"/MapGISSample/Map/MapShow/WuHan/WuHan.mapx");
//通过地图文档获取地图对象
map = mapDoc.getMaps().getMap(0);

//同步方法:通过地图视图对象设置地图
mMapView.setMap(map);
//异步方法:可监听地图的加载情况
mMapView.setMapAsync(map, new MapViewFinishCallback() {
    @Override
    public void onDidFinish(boolean arg0) {
        if (arg0) {
            //地图加载完成
        } else {
            //地图加载失败
        }
    }
});

代码说明:利用setMap或setMapAsync将地图Map赋予给地图视图MapView时,Map对象需定义为成员变量,从而实现生命周期的正确管理。

四、通过数据库创建图层,从而构建Map:setMap / setMapAsync

通过数据库DataBase获取数据,创建图层,从而构建Map,然后调用setMap / setMapAsync方法加载地图。此方法只适用于离线矢量数据(.hdb数据库,兼容.mgdb数据库)

0203MapView加载地图接口2.png


        String offlineDataBasePath = MainActivity.rootPath+ "/MapGISSample/Map/MapShow/WuHan/WuHan.hdb";

        Map map = new Map();
        String   strGDBName = "";
       
        int offPath = offlineDataBasePath.lastIndexOf(".");
        int offName = offlineDataBasePath.lastIndexOf("/");
        strGDBName = offlineDataBasePath.substring(offName, offPath);
        //构造数据库对象
        //DataBase dataBase = new DataBase();
        Server  svr = new Server();
        if(svr.connect("MapGISLocalPlus", "", "") > 0)
        {
        	//连接数据库
        	 boolean bAttach = svr.attachGDB(strGDBName, offlineDataBasePath, null);
        	 if(bAttach)
        	 {
        		 //打开数据库
        	     DataBase dataBase = svr.openGDB(strGDBName);
             	// DataBase dataBase = DataBase.openByURLNew(offlineDataBasePath);
                  //dataBase.open(offlineDataBasePath);
                  if (dataBase.hasOpened()) {
                      //简单要素类
                     // IntList list1 = dataBase.getXclseIDs(XClsType.SFCls, 0);
                      int[] list1 = dataBase.getXclses(XClsType.XSFCls, 0);
                      for (int i = 0; i < list1.length; i++) {
                          //创建VectorLayer图层对象,设置URL和Name
                          SFeatureCls  sfCls = new SFeatureCls(dataBase);
                          if(sfCls.open(list1[i], 0) > 0)
                          {
                          	VectorLayer vectorLayer = new VectorLayer(VectorLayerType.SFclsLayer);
                              if(vectorLayer.attachData(sfCls))
                              {
                              	 //添加图层
                                  map.append(vectorLayer);
                              }                 
                          }
                      }

                      //注记类
                      int[] list2 = dataBase.getXclses(XClsType.XACls, 0);
                      for (int i = 0; i < list2.length; i++) {
                          //创建VectorLayer图层对象,设置URL和Name
                      	AnnotationCls annCls = new AnnotationCls(dataBase);
                      	if(annCls.open(list1[i], 0) > 0)
                          {
          	                VectorLayer vectorLayer = new VectorLayer(VectorLayerType.AnnLayer);
          	                if(vectorLayer.attachData(annCls))
          	                {
          	                	 //添加图层
          		                map.append(vectorLayer);
          		                annCls.close();
          	                }
                          }
                      }

                      //同步加载地图
                      mapView.setMap(map);

                      //异步方法
//                      mapView.setMapAsync(map, new MapViewFinishCallback() {
//                          @Override
//                          public void onDidFinish(boolean arg0) {
//                              if (arg0) {
//                                  Toast.makeText(ShowDocVectorMap_Activity.this, "地图加载完成\n说明:地图显示的效果依mapx决定,从数据库中读取数据只能显示属于最原始的效果", Toast.LENGTH_SHORT).show();
//                              } else {
//                                  Toast.makeText(ShowDocVectorMap_Activity.this, "地图加载失败", Toast.LENGTH_SHORT).show();
//                              }
//                          }
//                      });
                  } 
        	 }	 
        }

加载离线瓦片地图

加载离线瓦片地图有如下方式:

一、参考离线矢量地图文档前3种方式

可以参考离线矢量地图文档前3种方式加载显示离线瓦片地图,前提是必须事先组织配置好瓦片地图的mapx地图文档文件。

1、加载离线瓦片地图文档: loadFromDocument / loadFromDocumentAsync

2、加载离线瓦片地图文档对应索引的瓦片地图:loadFromDocument / loadFromDocumentAsync

3、通过离线瓦片地图文档获取Map:setMap / setMapAsync

二、【推荐】通过ImageLayer的方法创建服务图层,从而构建Map:setMap / setMapAsync

通过ImageLayer类创建服务图层,调用服务图层的setURL()方法设置离线瓦片地图文件路径,然后通过Map类的append()方法加入到地图中,最后调用MapView类的setMap/setMapAsync方法将地图加载到地图容器中显示。

0203MapView加载地图接口2.png 0208ImageLayer类接口.png 0209MapServer类接口.png


       String offlineDataBasePath = MainActivity.rootPath+ "/MapGISSample/Map/MapShow/WorldMKTTile.mut";
       //创建服务图层
    	ImageLayer serverLayer = new ImageLayer();
        //创建地图服务
        MapServer mapserver = ImageLayer.createMapServer(MapServer.MAPSERVER_TYPE_TDF);
        //为地图服务设置URL:mut瓦片文件路径
        mapserver.setURL(offlineTileFilePath);
        //为服务图层设置地图服务
        serverLayer.setMapServer(mapserver);

        map = new Map();
        map.append(serverLayer);

        //同步方法
        mapView.setMap(map);

        //异步方法
//        mapView.setMapAsync(map, new MapView.MapViewFinishCallback() {
//            @Override
//            public void onDidFinish(boolean arg0) {
//                if (arg0) {
//                    Toast.makeText(ShowDocTileMap_Activity.this, "瓦片地图加载成功", Toast.LENGTH_SHORT).show();
//                } else {
//                    Toast.makeText(ShowDocTileMap_Activity.this, "瓦片地图加载失败", Toast.LENGTH_SHORT).show();
//                }
//            }
//        });

加载离线栅格数据

加载离线栅格数据有如下方式:

一、通过地图文档方式加载

此方式需将栅格数据图层先组织为地图文档,将地图文档与数据库hdb文件一起拷贝到移动端设备。

        //地图文档路径
        String strMapxPath = MainActivity.rootPath + "/MapGISSample/Map/MapShow/RasterDataset/RaseterDataset1.mapx";
        //加载离线栅格数据地图文档
        mapView.loadFromFile(strMapxPath);
        //加载地图的监听
        mapView.setMapLoadListener(new MapView.MapViewMapLoadListener() {
            @Override
            public void mapViewWillStartLoadingMap(MapView mapView, String s) {
                Toast.makeText(ShowDocRasterDataset_Activity.this, "开始加载地图", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void mapViewDidFinishLoadingMap(MapView mapView, String s) {
                Toast.makeText(ShowDocRasterDataset_Activity.this, "地图加载完成", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void mapViewDidFailLoadingMap(MapView mapView, String s) {
                Toast.makeText(ShowDocRasterDataset_Activity.this, "地图加载失败", Toast.LENGTH_SHORT).show();
            }
        });

二、通过图层方式加载

此方式直接读取hdb数据库上的栅格图层数据或者离线本地栅格文件进行显示,需要先将数据库hdb文件或栅格数据文件一起拷贝到移动端设备。


        //数据库文件路径
        String dbFilePath = MainActivity.rootPath + "/MapGISSample/Map/MapShow/RasterDataset/rasterdataset.hdb";
        //附加数据库
        AttachDatabase(dbFilePath);

        int pos = dbFilePath.lastIndexOf('/');
        if (pos < 0) return;
        String dbName = dbFilePath.substring(pos+1);
        pos = dbName.lastIndexOf('.');
        if (pos > 0)
            dbName = dbName.substring(0, pos);
        String dirPath = dbFilePath.substring(0,  dbFilePath.lastIndexOf('/'));
        //数据源
        Server svr = new Server();
        if (svr.connect("MapGISLocalPlus", "", "") < 1)
            return;
        //打开数据库
        DataBase db = svr.openGDB(dbName);
        if (db == null) {
            svr.disConnect();
            return;
        }

        String dbUrl = db.getURL();
        int[] rsIDs = db.getXclses(XClsType.XRds, 0 );
        if (rsIDs == null || rsIDs.length < 1){
            db.close();
            svr.disConnect();
            return;
        }

        ArrayList strList = new ArrayList();
        for (int id:rsIDs) {
            String rsName = db.getXclsName(XClsType.XRds, id);
            strList.add(rsName);
            break;
        }

        db.close();
        svr.disConnect();
        if (strList.size() < 1)
            return;
        //hdb数据库中的栅格图层
        m_map = new Map();
        RasterLayer layer = new RasterLayer();
        String  layerUrl = dbUrl+ "/ras/" + strList.get(0);
        boolean bFlag = layer.setURL(layerUrl);
        if (layer.connectData()){
            m_map.append(layer);
        }
        //栅格数据tif文件
        RasterLayer layer2 = new RasterLayer();
        layer2.setURL("file://@"+ dirPath + "/gaocheng.tif");
        if (layer2.connectData()){
            m_map.append(layer2);
        }
        //通过地图视图对象设置地图
        mapView.setMap(m_map);
        mapView.restore(true);
        //加载地图的监听
        mapView.setMapLoadListener(new MapView.MapViewMapLoadListener() {
            @Override
            public void mapViewWillStartLoadingMap(MapView mapView, String s) {
                Toast.makeText(ShowDocRasterDataset_Activity.this, "开始加载地图", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void mapViewDidFinishLoadingMap(MapView mapView, String s) {
                Toast.makeText(ShowDocRasterDataset_Activity.this, "地图加载完成", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void mapViewDidFailLoadingMap(MapView mapView, String s) {
                Toast.makeText(ShowDocRasterDataset_Activity.this, "地图加载失败", Toast.LENGTH_SHORT).show();
            }
        });

    private boolean AttachDatabase(String dbFilePath)
    {
        int pos = dbFilePath.lastIndexOf('/');
        if (pos < 0) return  false;
        String dbName = dbFilePath.substring(pos+1);
        pos = dbName.lastIndexOf('.');
        if (pos > 0)
            dbName = dbName.substring(0, pos);
        //数据源
        Server svr = new Server();
        File file = new File(dbFilePath);
        if (!file.exists())
            return  false;
      
        if (svr.connect("MapGISLocalPlus", "", "") < 1)
            return  false;
        
        int[] dbIDs = svr.getGdbs();
        if (dbIDs != null && dbIDs.length > 0){
            for (int a:dbIDs ) {
                svr.detachGDB(a);
            }
        }
        //附加数据库
        long rtn = svr.attachDB(dbName, dbFilePath, "");
        svr.disConnect();
        return  false;
    }

显示效果如下所示:

离线矢量地图显示效果.jpg 离线瓦片地图显示效果.jpg